using System;
using System.Collections.Generic;
using UnityEngine;
using AudioType = Framework.Audio.AudioType;

namespace Audio
{
    /// <summary>
    /// 单独分离的音频资源加载器，方便后续升级资源加载策略
    /// </summary>
    public class AudioSourceHandler : IAudioSourceHandler
    {

        private static readonly Dictionary<AudioType, string> _AUDIO_PATH = new Dictionary<AudioType, string>()
                                                                            {
                                                                                {AudioType.BGM, "BGM"},
                                                                                {AudioType.BSE, "BSE"},
                                                                                {AudioType.SOUND, "SE"}
                                                                            };

        private string _audioSourcePath;

        private Dictionary<string, AudioClip> _audioSource;
        private Dictionary<string, int> _audioReferenceCount;

#if UNITY_EDITOR
        //用于编辑器状态下监视资源状态
        public Dictionary<string, string> editorLog;
#endif

        private string AudioFullPath(AudioType audioType, string audioName)
        {
            audioName = audioName.Replace("\\", "/");
            return $"{this._audioSourcePath}/{_AUDIO_PATH[audioType]}/{audioName}";
        }


        public AudioSourceHandler(string audioSourcePath)
        {
            this._audioSourcePath = audioSourcePath;
            this._audioReferenceCount = new Dictionary<string, int>();
            this._audioSource = new Dictionary<string, AudioClip>();
#if UNITY_EDITOR
            this.editorLog = new Dictionary<string, string>();
#endif
        }


        /// <summary>
        /// 获取一个音频资源
        /// </summary>
        /// <param name="audioType"></param>
        /// <param name="audioName"></param>
        /// <returns></returns>
        public AudioClip GetAudioClip(ushort audioType, string audioName)
        {
            var audioKey = audioType + audioName;
            //当指定音效没有或者其资源为null时，通过ab包加载
            if (!this._audioSource.ContainsKey(audioKey) || this._audioSource[audioKey] == null)
            {
                this._audioSource[audioKey] = Resources.Load<AudioClip>(this.AudioFullPath((AudioType)audioType, audioName));
                this._audioReferenceCount[audioKey] = 0;
            }

            var audioClip = this._audioSource[audioKey];
            this._audioReferenceCount[audioKey] += audioClip != null ? 1 : 0;
#if UNITY_EDITOR
            this.RefreshLog();
#endif
            return audioClip;
        }

        public void OnAudioInvalid(ushort audioGroup, string audioName)
        {
            var audioKey = audioGroup + audioName;
            if (this._audioReferenceCount.ContainsKey(audioKey) && this._audioReferenceCount[audioKey] >= 1)
            {
                this._audioReferenceCount[audioKey] -= 1;
                if (this._audioReferenceCount[audioKey] == 0)
                {
                    if (audioGroup == 0 || audioGroup == 1)
                    {
                        var clip = this._audioSource[audioKey];
                        this._audioSource[audioKey] = null;
                        Resources.UnloadAsset(clip);
                    }
#if UNITY_EDITOR
                    this.RefreshLog();
#endif
                }
            }
        }

        /// <summary>
        /// 卸载所有未使用的音效资源
        /// </summary>
        public void UnLoadAllInvalid()
        {
            List<string> sourceKeys = new List<string>(this._audioSource.Keys);
            for (int i = sourceKeys.Count - 1; i >= 0; i--)
            {
                var audioSourceKey = sourceKeys[i];
                if (this._audioReferenceCount[audioSourceKey] == 0)
                {
                    // ushort group = ushort.Parse(audioSourceKey.Substring(0, 1));
                    // string audioName = audioSourceKey.Substring(1);
                    var clip = this._audioSource[audioSourceKey];
                    Resources.UnloadAsset(clip);

                    this._audioSource.Remove(audioSourceKey);
                    this._audioReferenceCount.Remove(audioSourceKey);
#if UNITY_EDITOR
                    this.editorLog.Remove(audioSourceKey);
#endif
                }
            }
#if UNITY_EDITOR
            this.RefreshLog();
#endif
        }


        public void RefreshLog()
        {
#if UNITY_EDITOR
            foreach (var audioSourceKey in this._audioSource.Keys)
            {
                this.editorLog[audioSourceKey] = $"\t{this._audioSource[audioSourceKey] != null} \t{this._audioReferenceCount[audioSourceKey]}";
            }
#endif
        }

    }
}